package controller

import (
	"GoTime/models"
	. "GoTime/utils"
	"encoding/json"
	"log"
	"net/http"
	"time"

	"github.com/beego/beego/validation"
	"github.com/gin-gonic/gin"
	"github.com/spf13/cast"
	"xorm.io/xorm"
)

// SchoolLogin 驾校管理人员登陆
func SchoolLogin(c *gin.Context) {
	valid := validation.Validation{}
	valid.Required(c.PostForm("name"), "name").Message("请输入用户名")
	valid.Required(c.PostForm("password"), "password").Message("请输入密码")
	if valid.HasErrors() {
		for _, err := range valid.Errors {
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Message})
			return
		}
	}
	school, _ := new(models.School).SchoolLogin(c.PostForm("name"))
	if school.Id == 0 {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "用户不存在"})
		return
	}
	if school.Password != Md5(c.PostForm("password")) {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "密码错误"})
		return
	}
	token, err := CreateToken(school.Id, school.InstitutionCode)
	log.Println(token, err)
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "登录成功", "data": gin.H{"token": token, "school_id": school.Id, "user_id": school.UserId, "isschool": "1", "institution_code": school.InstitutionCode, "name": school.NameShort, "province": school.Province, "city": school.City, "district": school.District, "pacttype": school.Pacttype}})
	return
}

func AddSchool(c *gin.Context) {
	// 接收前端提交的表单数据
	school := new(models.School)                 // 创建一个新的School模型实例
	user := new(models.User)                     // 创建一个新的User模型实例
	if err := c.ShouldBind(school); err != nil { // 尝试将请求中的数据绑定到school结构体，如果绑定过程中出现错误
		// 返回HTTP状态码200，以及JSON格式的错误信息，提示客户端参数错误
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误", "data": err.Error()})
		return
	}
	if err := c.ShouldBind(user); err != nil { // 尝试将请求中的数据绑定到user结构体，如果绑定过程中出现错误
		// 返回HTTP状态码200，以及JSON格式的错误信息，提示客户端参数错误
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误", "data": err.Error()})
		return
	}
	var engine *xorm.Engine        // 声明一个指向xorm引擎的指针
	engine = models.Engine         // 将models包中的Engine赋值给engine变量
	session := engine.NewSession() // 创建一个新的数据库会话
	defer session.Close()          // 确保在函数结束时关闭会话，释放资源

	// 开始一个新的事务，在执行任何数据库操作之前调用Begin()
	err := session.Begin()
	if err != nil {
		// 如果开始事务出错，回滚事务以确保数据一致性
		session.Rollback()
		// 返回HTTP状态码200，以及JSON格式的错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}

	user.Type = "2"
	if len(school.LicenceNumber) >= 6 {
		user.Password = Md5(school.LicenceNumber[len(school.LicenceNumber)-6:])
	}
	user.Isused = "1"
	user.Name = school.NameShort
	// 向数据库中插入新的用户记录
	_, err = session.Insert(user)
	if err != nil {
		// 如果插入操作出错，回滚事务
		session.Rollback()
		// 返回HTTP状态码200，以及JSON格式的错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}
	school.UserId = user.Id
	school.RecordStatus = "0" //备案状态 0：未备案   1：已备案
	school.ApprovalStatus = "0"
	school.Registernum = 0
	school.Signmoney = 50
	school.Lownum = 100
	school.Isused = "1"
	school.Addtime = time.Now().Format("2006-01-02 15:04:05")
	school.Transfertype = "1"
	school.Pacttype = "1"
	// 向数据库中插入新的学校记录
	_, err = session.Insert(school)
	if err != nil {
		// 如果插入操作出错，回滚事务
		session.Rollback()
		// 返回HTTP状态码200，以及JSON格式的错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}
	// 提交事务，确保所有操作都被成功记录
	err = session.Commit()
	if err != nil {
		// 如果提交事务出错，回滚事务
		session.Rollback()
		// 返回HTTP状态码200，以及JSON格式的错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}
	//log.Println(school) // 记录插入成功的学校信息到日志

	// 如果没有错误，返回成功信息和学校数据
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "添加成功", "data": "school"})
	return // 结束函数执行

}

func GetSchoolDetail(c *gin.Context) {
	id := c.Query("id") // 从请求参数中获取id值

	valid := validation.Validation{}          // 创建一个Validation对象用于数据验证
	valid.Required(id, "id").Message("请输入id") // 验证id字段是否为空，并设置自定义错误信息

	// 检查是否有验证错误
	if valid.HasErrors() {
		for _, err := range valid.Errors { // 遍历所有的验证错误
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Message, "data": nil}) // 返回JSON格式的错误信息
			return                                                                     // 结束函数执行
		}
	}
	// 调用GetSchoolById方法根据id获取学校信息
	ok, school, err := new(models.School).GetSchoolById(cast.ToInt(id))
	if err != nil { // 如果发生错误
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "获取失败", "data": nil}) // 返回获取失败的错误信息
		return                                                                // 结束函数执行
	} else if !ok { // 如果驾校不存在
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "驾校不存在", "data": nil}) // 返回驾校不存在的错误信息
		return                                                                 // 结束函数执行
	}

	// 如果没有错误，返回成功信息和学校数据
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "获取成功", "data": school})
	return // 结束函数执行

}

func EditSchool(c *gin.Context) {
	// 接收前端提交的表单数据
	school := new(models.School)                 // 创建一个新的School模型实例
	user := new(models.User)                     // 创建一个新的User模型实例
	if err := c.ShouldBind(school); err != nil { // 尝试将请求中的数据绑定到school结构体，如果绑定过程中出现错误
		// 返回HTTP状态码200，以及JSON格式的错误信息，提示客户端参数错误
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误", "data": err.Error()})
		return
	}
	school.Id = cast.ToInt(c.PostForm("id"))
	valid := validation.Validation{}                        // 创建一个Validation对象用于数据验证
	valid.Required(c.PostForm("id"), "id").Message("请输入id") // 验证id字段是否为空，并设置自定义错误信息
	// 检查是否有验证错误
	if valid.HasErrors() {
		for _, err := range valid.Errors { // 遍历所有的验证错误
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Message, "data": nil}) // 返回JSON格式的错误信息
			return                                                                     // 结束函数执行
		}
	}
	if err := c.ShouldBind(user); err != nil { // 尝试将请求中的数据绑定到user结构体，如果绑定过程中出现错误
		// 返回HTTP状态码200，以及JSON格式的错误信息，提示客户端参数错误
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误", "data": err.Error()})
		return
	}
	var engine *xorm.Engine        // 声明一个指向xorm引擎的指针
	engine = models.Engine         // 将models包中的Engine赋值给engine变量
	session := engine.NewSession() // 创建一个新的数据库会话
	defer session.Close()          // 确保在函数结束时关闭会话，释放资源

	// 开始一个新的事务，在执行任何数据库操作之前调用Begin()
	err := session.Begin()
	if err != nil {
		// 如果开始事务出错，回滚事务以确保数据一致性
		session.Rollback()
		// 返回HTTP状态码200，以及JSON格式的错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}

	// 根据id获取学校信息
	ok, oldschool, err := new(models.School).GetSchoolById(school.Id)
	if err != nil { // 如果发生错误
		session.Rollback()                                                    // 回滚事务
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "获取失败", "data": nil}) // 返回获取失败的错误信息
		return                                                                // 结束函数执行
	} else if !ok { // 如果驾校不存在
		session.Rollback()                                                     // 回滚事务
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "驾校不存在", "data": nil}) // 返回驾校不存在的错误信息
		return                                                                 // 结束函数执行
	}

	// 更新学校信息
	school.RecordStatus = "0"
	school.ApprovalStatus = "0"
	school.Addtime = oldschool.Addtime
	_, err = session.ID(school.Id).Update(school)
	if err != nil { // 如果更新失败
		session.Rollback()                                                    // 回滚事务
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "更新失败", "data": nil}) // 返回更新失败的错误信息
		return                                                                // 结束函数执行
	}

	// 提交事务，确保所有操作都被成功记录
	err = session.Commit()
	if err != nil {
		// 如果提交事务出错，回滚事务
		session.Rollback()
		// 返回HTTP状态码200，以及JSON格式的错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}
	//log.Println(school) // 记录插入成功的学校信息到日志

	// 如果没有错误，返回成功信息和学校数据
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "更新成功", "data": "school"})
	return // 结束函数执行

}

func RecordSchool(c *gin.Context) {
	var (
		schoolId string
	)

	// 从POST表单中获取id字段的值，并赋值给schoolId变量
	schoolId = c.PostForm("id")

	// 创建一个Validation对象用于数据验证
	valid := validation.Validation{}

	// 验证id字段是否为空，并设置自定义错误信息
	valid.Required(c.PostForm("id"), "id").Message("请输入id")

	// 检查是否有验证错误
	if valid.HasErrors() {
		// 遍历所有的验证错误
		for _, err := range valid.Errors {
			// 返回状态码201和相应的错误信息
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Message, "data": nil})
			return
		}
	}

	// 根据schoolId获取驾校信息
	ok, school, err := new(models.School).GetSchoolById(cast.ToInt(schoolId))

	// 检查是否存在错误或驾校是否存在
	if err != nil || !ok {
		// 如果存在错误或驾校不存在，返回状态码201和相应的错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "驾校不存在"})
		return
	}

	// 调用school的RecordSchool方法进行备案
	if err = school.RecordSchool(); err != nil {
		// 如果备案过程中发生错误，返回状态码201和相应的错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}

	// 如果备案成功，返回状态码200和成功信息
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "备案成功"})
	return

}

func GetSchoolInfo(c *gin.Context) {
	var (
		url     string                 // 用于存储签名URL
		retMap  map[string]interface{} // 用于存储API请求的返回结果
		reqType int64                  // 用于存储请求类型
		err     error                  // 用于存储错误信息
	)

	// 从查询参数中获取school_id字段的值
	schoolId := c.Query("school_id")

	// 检查school_id是否为空
	if schoolId == "" {
		// 如果school_id为空，返回状态码201和参数错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误"})
		return
	}

	// 根据schoolId获取驾校信息
	ok, school, err := new(models.School).GetSchoolById(cast.ToInt(schoolId))

	// 检查是否存在错误或驾校是否存在
	if err != nil || !ok {
		// 如果存在错误或驾校不存在，返回状态码201和驾校不存在信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "驾校不存在"})
		return
	}

	// 进行备案操作
	if url, err = GetSignURL("getschoolinfo-"+school.InstitutionCode, nil, reqType, school.Province, school.City); err != nil {
		// 如果生成签名URL时发生错误，返回状态码201和错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}

	// 创建ApiLog对象以记录API请求信息
	var apiLog models.ApiLog
	apiLog.Url = url         // 设置请求的URL
	apiLog.Param = ""        // 设置请求参数（这里为空）
	apiLog.Method = "POST"   // 设置请求方法为POST
	apiLog.Time = time.Now() // 设置请求时间

	// 发送API请求并获取返回结果
	if retMap, err = APIReq(url, nil, "GET"); err != nil {
		// 如果API请求发生错误，将retMap转换为JSON字符串并记录到apiLog中
		result, _ := json.Marshal(retMap)
		apiLog.Result = string(result)
		apiLog.Add() // 添加API日志记录
		// 返回状态码201和错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}

	// 如果API请求成功，将retMap转换为JSON字符串并记录到apiLog中
	result, _ := json.Marshal(retMap)
	apiLog.Result = string(result)
	apiLog.Add() // 添加API日志记录

	// 返回状态码200和成功信息，以及API请求的返回结果
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "成功", "data": retMap})
	return

}

func LicNumChange(c *gin.Context) {
	var (
		school models.School // 用于存储获取到的驾校信息
		err    error         // 用于存储错误信息
		ok     bool          // 用于存储获取驾校信息是否成功的标志
	)

	// 根据POST表单中的school_id获取驾校信息
	if ok, school, err = new(models.School).GetSchoolById(cast.ToInt(c.PostForm("school_id"))); !ok || err != nil {
		// 如果获取驾校信息失败或发生错误，返回状态码201和驾校不存在信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "驾校不存在"})
		return
	} else {
		// 如果获取驾校信息成功，进行驾校许可证编号变更操作
		if err = school.SchoolLicNumChange(c.PostForm("licnum"), school.Province, school.City); err != nil {
			// 如果变更过程中发生错误，返回状态码201和错误信息
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
			return
		}
	}

	// 如果变更成功，返回状态码200和变更成功信息
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "变更成功"})
	return

}

func GetSchoolBusinessScope(c *gin.Context) {

	// 根据查询参数中的驾校ID获取驾校信息
	ok, school, err := new(models.School).GetSchoolById(cast.ToInt(c.Query("school_id")))
	// 检查是否存在错误或驾校是否存在
	if err != nil || !ok {
		// 如果存在错误或驾校不存在，返回状态码201和相应的错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "驾校不存在"})
		return
	}
	// 如果驾校存在，返回状态码200和驾校的业务范围信息
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "获取驾校培训车型成功", "data": gin.H{"business_scope": school.BusinessScope}})
	return

}
